from django.shortcuts import render
from django.views import View
from django.http import HttpResponse,JsonResponse

# get_redis_connection函数功能：根据django配置文件获取指定redis配置连接
from django_redis import get_redis_connection

import re,random

from verifications.libs.captcha.captcha import captcha
from verifications.libs.yuntongxun.ccp_sms import CCP
from celery_tasks.sms.tasks import ccp_send_sms_code
# Create your views here.


# 接口：获取图片验证码
class ImageCodeView(View):

    def get(self, request, uuid):
        # 1、提取参数
        # 2、校验参数
        # 3、业务数据处理
        # 3.1、captcha生成图片验证码
        text, image_bytes = captcha.generate_captcha()
        # 3.2、保存验证码text到redis中; {img_<uuid> : 图片验证码}
        # (1)、获取redis连接
        conn = get_redis_connection('verify_code') # 2号库
        # (2)、使用conn连接对象把text写入
        # conn.set() --> 往redis中写入一个键值对，无有效期
        # conn.setex(键，有效时间秒，值) --> 写入含有有效期的键值对
        conn.setex('img_%s'%uuid, 300, text)
        # 4、构建响应 —— 返回验证码图片
        return HttpResponse(
            image_bytes, # 响应体数据是图片的字节数据
            content_type='image/jpeg' # 指定响应体参数格式/类型是图片jpg类型
        )

# 接口：短信验证码
class SMSCodeView(View):

    def get(self, request, mobile):
        # 1、提取参数
        # /sms_code/18588269037/?image_code=UYTG&image_code_id=b37cfb19-ab0b-4063-9657-24e185735c99
        # request.GET --> {"image_code": "UYTG", "image_code_id": .....}
        image_code = request.GET.get('image_code') # 'YUGH'
        uuid = request.GET.get('image_code_id')
        # 2、校验参数
        # 2.1、必要校验
        if not all([image_code, uuid]):
            return JsonResponse({'code': 400, 'errmsg': '缺少参数'})
        # 2.2、格式校验
        # 图形验证码格式：[a-zA-Z0-9]{4}
        if not re.match('^[a-zA-Z0-9]{4}$', image_code):
            return JsonResponse({'code': 400, 'errmsg': '图形验证码输入有误'})
        # uuid格式校验
        if not re.match('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$', uuid):
            return JsonResponse({'code': 400, 'errmsg': 'uuid格式有误'})

        # 2.3、业务性校验 —— 校验用户输入的图形验证码是否正确
        # (1)、获取redis连接
        conn = get_redis_connection('verify_code') # 2号库
        # (2)、读取uuid对应redis中的图形验证码
        image_code_from_redis = conn.get('img_%s'%uuid) # 过期返回None; b'YUGH'
        # TODO: 为了防止该图形验证码被重复使用，我们遵循"读取一次图形验证码，直接删除掉"
        conn.delete('img_%s'%uuid)
        # (3)、判断是否过期
        if not image_code_from_redis:
            # 过期了
            return JsonResponse({'code': 400, 'errmsg': '图形验证码过期。'})
        # (4)、比对用户输入是否正确
        #  'YUGH' ！= b'YUGH'.decode()
        #  'YUGH' ！= 'YUGH'
        if image_code.lower() != image_code_from_redis.decode().lower():
            return JsonResponse({'code': 400, 'errmsg': '图形验证码输入有误。'})

        # 3、业务数据处理
        # TODO: 发短信之前，需要先判断标志信息是否存在，如果存在则说明60秒之内发送过短信，此时不允许再发送
        send_flag = conn.get('send_flag_%s'%mobile)
        if send_flag:
            return JsonResponse({'code': 400, 'errmsg': '请勿重复发送短信。'})

        # (1)、随机产生6位数的短信验证码
        sms_code = "%06d" % random.randrange(0, 999999)
        # (2)、调用云通讯开发包发短信
        # ccp = CCP()
        # ccp.send_template_sms(mobile, [sms_code, 5], 1)
        # TODO: 以异步方式发短信
        ccp_send_sms_code.delay(mobile, sms_code)

        # TODO：使用redis的pipeline批量执行指令
        # 通过redis连接对象，获取管道对象(pipeline对象)
        p = conn.pipeline()
        # (3)、短信验证码写入redis: {sms_<手机号> ：短信验证码}
        # conn.setex('sms_%s'%mobile, 300, sms_code)
        p.setex('sms_%s'%mobile, 300, sms_code)
        # TODO: 成功发短信之后，需要在redis中记录一个标志信息，用于表示60秒之内发送过短信
        # 标志信息设计：{send_flag_<手机号> : -1}
        # conn.setex('send_flag_%s'%mobile, 60, -1)
        p.setex('send_flag_%s'%mobile, 60, -1)
        # 批量发送指令到服务端执行
        p.execute()

        # 4、构建响应
        return JsonResponse({'code': 0, 'errmsg': 'ok'})







